1   /*
2    * Copyright (C) 2009 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.collect;
18  
19  import static com.google.common.truth.Truth.assertThat;
20  
21  import com.google.common.annotations.GwtCompatible;
22  import com.google.common.base.Joiner;
23  import com.google.common.collect.ImmutableSortedMap.Builder;
24  import com.google.common.collect.testing.SortedMapInterfaceTest;
25  
26  import junit.framework.TestCase;
27  
28  import java.io.Serializable;
29  import java.util.Collections;
30  import java.util.Comparator;
31  import java.util.LinkedHashMap;
32  import java.util.Map;
33  import java.util.Map.Entry;
34  import java.util.SortedMap;
35  
36  /**
37   * Tests for {@link ImmutableSortedMap}.
38   *
39   * @author Kevin Bourrillion
40   * @author Jesse Wilson
41   * @author Jared Levy
42   */
43  @GwtCompatible(emulated = true)
44  public class ImmutableSortedMapTest extends TestCase {
45    // TODO: Avoid duplicating code in ImmutableMapTest
46  
47    public abstract static class AbstractMapTests<K, V>
48        extends SortedMapInterfaceTest<K, V> {
49      public AbstractMapTests() {
50        super(false, false, false, false, false);
51      }
52  
53      @Override protected SortedMap<K, V> makeEmptyMap() {
54        throw new UnsupportedOperationException();
55      }
56  
57      private static final Joiner joiner = Joiner.on(", ");
58  
59      @Override protected void assertMoreInvariants(Map<K, V> map) {
60        // TODO: can these be moved to MapInterfaceTest?
61        for (Entry<K, V> entry : map.entrySet()) {
62          assertEquals(entry.getKey() + "=" + entry.getValue(),
63              entry.toString());
64        }
65  
66        assertEquals("{" + joiner.join(map.entrySet()) + "}",
67            map.toString());
68        assertEquals("[" + joiner.join(map.entrySet()) + "]",
69            map.entrySet().toString());
70        assertEquals("[" + joiner.join(map.keySet()) + "]",
71            map.keySet().toString());
72        assertEquals("[" + joiner.join(map.values()) + "]",
73            map.values().toString());
74  
75        assertEquals(Sets.newHashSet(map.entrySet()), map.entrySet());
76        assertEquals(Sets.newHashSet(map.keySet()), map.keySet());
77      }
78    }
79  
80    public static class MapTests extends AbstractMapTests<String, Integer> {
81      @Override protected SortedMap<String, Integer> makeEmptyMap() {
82        return ImmutableSortedMap.of();
83      }
84  
85      @Override protected SortedMap<String, Integer> makePopulatedMap() {
86        return ImmutableSortedMap.of("one", 1, "two", 2, "three", 3);
87      }
88  
89      @Override protected String getKeyNotInPopulatedMap() {
90        return "minus one";
91      }
92  
93      @Override protected Integer getValueNotInPopulatedMap() {
94        return -1;
95      }
96    }
97  
98    public static class SingletonMapTests
99        extends AbstractMapTests<String, Integer> {
100     @Override protected SortedMap<String, Integer> makePopulatedMap() {
101       return ImmutableSortedMap.of("one", 1);
102     }
103 
104     @Override protected String getKeyNotInPopulatedMap() {
105       return "minus one";
106     }
107 
108     @Override protected Integer getValueNotInPopulatedMap() {
109       return -1;
110     }
111   }
112 
113   public static class HeadMapTests extends AbstractMapTests<String, Integer> {
114     @Override protected SortedMap<String, Integer> makePopulatedMap() {
115       return ImmutableSortedMap.of("a", 1, "b", 2, "c", 3, "d", 4, "e", 5)
116           .headMap("d");
117     }
118 
119     @Override protected String getKeyNotInPopulatedMap() {
120       return "d";
121     }
122 
123     @Override protected Integer getValueNotInPopulatedMap() {
124       return 4;
125     }
126   }
127 
128   public static class HeadMapInclusiveTests extends AbstractMapTests<String, Integer> {
129     @Override protected SortedMap<String, Integer> makePopulatedMap() {
130       return ImmutableSortedMap.of("a", 1, "b", 2, "c", 3, "d", 4, "e", 5)
131           .headMap("c", true);
132     }
133 
134     @Override protected String getKeyNotInPopulatedMap() {
135       return "d";
136     }
137 
138     @Override protected Integer getValueNotInPopulatedMap() {
139       return 4;
140     }
141   }
142 
143   public static class TailMapTests extends AbstractMapTests<String, Integer> {
144     @Override protected SortedMap<String, Integer> makePopulatedMap() {
145       return ImmutableSortedMap.of("a", 1, "b", 2, "c", 3, "d", 4, "e", 5)
146           .tailMap("b");
147     }
148 
149     @Override protected String getKeyNotInPopulatedMap() {
150       return "a";
151     }
152 
153     @Override protected Integer getValueNotInPopulatedMap() {
154       return 1;
155     }
156   }
157 
158   public static class TailExclusiveMapTests extends AbstractMapTests<String, Integer> {
159     @Override protected SortedMap<String, Integer> makePopulatedMap() {
160       return ImmutableSortedMap.of("a", 1, "b", 2, "c", 3, "d", 4, "e", 5)
161           .tailMap("a", false);
162     }
163 
164     @Override protected String getKeyNotInPopulatedMap() {
165       return "a";
166     }
167 
168     @Override protected Integer getValueNotInPopulatedMap() {
169       return 1;
170     }
171   }
172 
173   public static class SubMapTests extends AbstractMapTests<String, Integer> {
174     @Override protected SortedMap<String, Integer> makePopulatedMap() {
175       return ImmutableSortedMap.of("a", 1, "b", 2, "c", 3, "d", 4, "e", 5)
176           .subMap("b", "d");
177     }
178 
179     @Override protected String getKeyNotInPopulatedMap() {
180       return "a";
181     }
182 
183     @Override protected Integer getValueNotInPopulatedMap() {
184       return 4;
185     }
186   }
187 
188   public static class CreationTests extends TestCase {
189     public void testEmptyBuilder() {
190       ImmutableSortedMap<String, Integer> map
191           = ImmutableSortedMap.<String, Integer>naturalOrder().build();
192       assertEquals(Collections.<String, Integer>emptyMap(), map);
193     }
194 
195     public void testSingletonBuilder() {
196       ImmutableSortedMap<String, Integer> map
197           = ImmutableSortedMap.<String, Integer>naturalOrder()
198               .put("one", 1)
199               .build();
200       assertMapEquals(map, "one", 1);
201     }
202 
203     public void testBuilder() {
204       ImmutableSortedMap<String, Integer> map
205           = ImmutableSortedMap.<String, Integer>naturalOrder()
206               .put("one", 1)
207               .put("two", 2)
208               .put("three", 3)
209               .put("four", 4)
210               .put("five", 5)
211               .build();
212       assertMapEquals(map,
213           "five", 5, "four", 4, "one", 1, "three", 3, "two", 2);
214     }
215 
216     public void testBuilder_withImmutableEntry() {
217       ImmutableSortedMap<String, Integer> map =
218           ImmutableSortedMap.<String, Integer>naturalOrder()
219               .put(Maps.immutableEntry("one", 1))
220               .build();
221       assertMapEquals(map, "one", 1);
222     }
223 
224     public void testBuilder_withImmutableEntryAndNullContents() {
225       Builder<String, Integer> builder =
226           ImmutableSortedMap.naturalOrder();
227       try {
228         builder.put(Maps.immutableEntry("one", (Integer) null));
229         fail();
230       } catch (NullPointerException expected) {
231       }
232       try {
233         builder.put(Maps.immutableEntry((String) null, 1));
234         fail();
235       } catch (NullPointerException expected) {
236       }
237     }
238 
239     private static class StringHolder {
240       String string;
241     }
242 
243     public void testBuilder_withMutableEntry() {
244       ImmutableSortedMap.Builder<String, Integer> builder =
245           ImmutableSortedMap.naturalOrder();
246       final StringHolder holder = new StringHolder();
247       holder.string = "one";
248       Entry<String, Integer> entry = new AbstractMapEntry<String, Integer>() {
249         @Override public String getKey() {
250           return holder.string;
251         }
252         @Override public Integer getValue() {
253           return 1;
254         }
255       };
256 
257       builder.put(entry);
258       holder.string = "two";
259       assertMapEquals(builder.build(), "one", 1);
260     }
261 
262     public void testBuilderPutAllWithEmptyMap() {
263       ImmutableSortedMap<String, Integer> map
264           = ImmutableSortedMap.<String, Integer>naturalOrder()
265               .putAll(Collections.<String, Integer>emptyMap())
266               .build();
267       assertEquals(Collections.<String, Integer>emptyMap(), map);
268     }
269 
270     public void testBuilderPutAll() {
271       Map<String, Integer> toPut = new LinkedHashMap<String, Integer>();
272       toPut.put("one", 1);
273       toPut.put("two", 2);
274       toPut.put("three", 3);
275       Map<String, Integer> moreToPut = new LinkedHashMap<String, Integer>();
276       moreToPut.put("four", 4);
277       moreToPut.put("five", 5);
278 
279       ImmutableSortedMap<String, Integer> map
280           = ImmutableSortedMap.<String, Integer>naturalOrder()
281               .putAll(toPut)
282               .putAll(moreToPut)
283               .build();
284       assertMapEquals(map,
285           "five", 5, "four", 4, "one", 1, "three", 3, "two", 2);
286     }
287 
288     public void testBuilderReuse() {
289       Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
290       ImmutableSortedMap<String, Integer> mapOne = builder
291           .put("one", 1)
292           .put("two", 2)
293           .build();
294       ImmutableSortedMap<String, Integer> mapTwo = builder
295           .put("three", 3)
296           .put("four", 4)
297           .build();
298 
299       assertMapEquals(mapOne, "one", 1, "two", 2);
300       assertMapEquals(mapTwo, "four", 4, "one", 1, "three", 3, "two", 2);
301     }
302 
303     public void testBuilderPutNullKey() {
304       Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
305       try {
306         builder.put(null, 1);
307         fail();
308       } catch (NullPointerException expected) {
309       }
310     }
311 
312     public void testBuilderPutNullValue() {
313       Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
314       try {
315         builder.put("one", null);
316         fail();
317       } catch (NullPointerException expected) {
318       }
319     }
320 
321     public void testBuilderPutNullKeyViaPutAll() {
322       Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
323       try {
324         builder.putAll(Collections.<String, Integer>singletonMap(null, 1));
325         fail();
326       } catch (NullPointerException expected) {
327       }
328     }
329 
330     public void testBuilderPutNullValueViaPutAll() {
331       Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
332       try {
333         builder.putAll(Collections.<String, Integer>singletonMap("one", null));
334         fail();
335       } catch (NullPointerException expected) {
336       }
337     }
338 
339     public void testPuttingTheSameKeyTwiceThrowsOnBuild() {
340       Builder<String, Integer> builder
341           = ImmutableSortedMap.<String, Integer>naturalOrder()
342               .put("one", 1)
343               .put("one", 2); // throwing on this line would be even better
344 
345       try {
346         builder.build();
347         fail();
348       } catch (IllegalArgumentException expected) {
349       }
350     }
351 
352     public void testOf() {
353       assertMapEquals(
354           ImmutableSortedMap.of("one", 1),
355           "one", 1);
356       assertMapEquals(
357           ImmutableSortedMap.of("one", 1, "two", 2),
358           "one", 1, "two", 2);
359       assertMapEquals(
360           ImmutableSortedMap.of("one", 1, "two", 2, "three", 3),
361           "one", 1, "three", 3, "two", 2);
362       assertMapEquals(
363           ImmutableSortedMap.of("one", 1, "two", 2, "three", 3, "four", 4),
364           "four", 4, "one", 1, "three", 3, "two", 2);
365       assertMapEquals(
366           ImmutableSortedMap.of(
367               "one", 1, "two", 2, "three", 3, "four", 4, "five", 5),
368           "five", 5, "four", 4, "one", 1, "three", 3, "two", 2);
369     }
370 
371     public void testOfNullKey() {
372       Integer n = null;
373       try {
374         ImmutableSortedMap.of(n, 1);
375         fail();
376       } catch (NullPointerException expected) {
377       }
378 
379       try {
380         ImmutableSortedMap.of("one", 1, null, 2);
381         fail();
382       } catch (NullPointerException expected) {
383       }
384     }
385 
386     public void testOfNullValue() {
387       try {
388         ImmutableSortedMap.of("one", null);
389         fail();
390       } catch (NullPointerException expected) {
391       }
392 
393       try {
394         ImmutableSortedMap.of("one", 1, "two", null);
395         fail();
396       } catch (NullPointerException expected) {
397       }
398     }
399 
400     public void testOfWithDuplicateKey() {
401       try {
402         ImmutableSortedMap.of("one", 1, "one", 1);
403         fail();
404       } catch (IllegalArgumentException expected) {
405       }
406     }
407 
408     public void testCopyOfEmptyMap() {
409       ImmutableSortedMap<String, Integer> copy
410           = ImmutableSortedMap.copyOf(Collections.<String, Integer>emptyMap());
411       assertEquals(Collections.<String, Integer>emptyMap(), copy);
412       assertSame(copy, ImmutableSortedMap.copyOf(copy));
413       assertSame(Ordering.natural(), copy.comparator());
414     }
415 
416     public void testCopyOfSingletonMap() {
417       ImmutableSortedMap<String, Integer> copy
418           = ImmutableSortedMap.copyOf(Collections.singletonMap("one", 1));
419       assertMapEquals(copy, "one", 1);
420       assertSame(copy, ImmutableSortedMap.copyOf(copy));
421       assertSame(Ordering.natural(), copy.comparator());
422     }
423 
424     public void testCopyOf() {
425       Map<String, Integer> original = new LinkedHashMap<String, Integer>();
426       original.put("one", 1);
427       original.put("two", 2);
428       original.put("three", 3);
429 
430       ImmutableSortedMap<String, Integer> copy
431           = ImmutableSortedMap.copyOf(original);
432       assertMapEquals(copy, "one", 1, "three", 3, "two", 2);
433       assertSame(copy, ImmutableSortedMap.copyOf(copy));
434       assertSame(Ordering.natural(), copy.comparator());
435     }
436 
437     public void testCopyOfExplicitComparator() {
438       Comparator<String> comparator = Ordering.natural().reverse();
439       Map<String, Integer> original = new LinkedHashMap<String, Integer>();
440       original.put("one", 1);
441       original.put("two", 2);
442       original.put("three", 3);
443 
444       ImmutableSortedMap<String, Integer> copy
445           = ImmutableSortedMap.copyOf(original, comparator);
446       assertMapEquals(copy, "two", 2, "three", 3, "one", 1);
447       assertSame(copy, ImmutableSortedMap.copyOf(copy, comparator));
448       assertSame(comparator, copy.comparator());
449     }
450 
451     public void testCopyOfImmutableSortedSetDifferentComparator() {
452       Comparator<String> comparator = Ordering.natural().reverse();
453       Map<String, Integer> original
454           = ImmutableSortedMap.of("one", 1, "two", 2, "three", 3);
455       ImmutableSortedMap<String, Integer> copy
456           = ImmutableSortedMap.copyOf(original, comparator);
457       assertMapEquals(copy, "two", 2, "three", 3, "one", 1);
458       assertSame(copy, ImmutableSortedMap.copyOf(copy, comparator));
459       assertSame(comparator, copy.comparator());
460     }
461 
462     public void testCopyOfSortedNatural() {
463       SortedMap<String, Integer> original = Maps.newTreeMap();
464       original.put("one", 1);
465       original.put("two", 2);
466       original.put("three", 3);
467 
468       ImmutableSortedMap<String, Integer> copy
469           = ImmutableSortedMap.copyOfSorted(original);
470       assertMapEquals(copy, "one", 1, "three", 3, "two", 2);
471       assertSame(copy, ImmutableSortedMap.copyOfSorted(copy));
472       assertSame(Ordering.natural(), copy.comparator());
473     }
474 
475     public void testCopyOfSortedExplicit() {
476       Comparator<String> comparator = Ordering.natural().reverse();
477       SortedMap<String, Integer> original = Maps.newTreeMap(comparator);
478       original.put("one", 1);
479       original.put("two", 2);
480       original.put("three", 3);
481 
482       ImmutableSortedMap<String, Integer> copy
483           = ImmutableSortedMap.copyOfSorted(original);
484       assertMapEquals(copy, "two", 2, "three", 3, "one", 1);
485       assertSame(copy, ImmutableSortedMap.copyOfSorted(copy));
486       assertSame(comparator, copy.comparator());
487     }
488 
489     private static class IntegerDiv10 implements Comparable<IntegerDiv10> {
490       final int value;
491 
492       IntegerDiv10(int value) {
493         this.value = value;
494       }
495 
496       @Override
497       public int compareTo(IntegerDiv10 o) {
498         return value / 10 - o.value / 10;
499       }
500 
501       @Override public String toString() {
502         return Integer.toString(value);
503       }
504     }
505 
506     public void testCopyOfDuplicateKey() {
507       Map<IntegerDiv10, String> original = ImmutableMap.of(
508           new IntegerDiv10(3), "three",
509           new IntegerDiv10(20), "twenty",
510           new IntegerDiv10(11), "eleven",
511           new IntegerDiv10(35), "thirty five",
512           new IntegerDiv10(12), "twelve"
513       );
514 
515       try {
516         ImmutableSortedMap.copyOf(original);
517         fail("Expected IllegalArgumentException");
518       } catch (IllegalArgumentException expected) {
519       }
520     }
521 
522     public void testImmutableMapCopyOfImmutableSortedMap() {
523       IntegerDiv10 three = new IntegerDiv10(3);
524       IntegerDiv10 eleven = new IntegerDiv10(11);
525       IntegerDiv10 twelve = new IntegerDiv10(12);
526       IntegerDiv10 twenty = new IntegerDiv10(20);
527       Map<IntegerDiv10, String> original = ImmutableSortedMap.of(
528           three, "three", eleven, "eleven", twenty, "twenty");
529       Map<IntegerDiv10, String> copy = ImmutableMap.copyOf(original);
530       assertTrue(original.containsKey(twelve));
531       assertFalse(copy.containsKey(twelve));
532     }
533 
534     public void testBuilderReverseOrder() {
535       ImmutableSortedMap<String, Integer> map
536           = ImmutableSortedMap.<String, Integer>reverseOrder()
537               .put("one", 1)
538               .put("two", 2)
539               .put("three", 3)
540               .put("four", 4)
541               .put("five", 5)
542               .build();
543       assertMapEquals(map,
544           "two", 2, "three", 3, "one", 1, "four", 4, "five", 5);
545       assertEquals(Ordering.natural().reverse(), map.comparator());
546     }
547 
548     public void testBuilderComparator() {
549       Comparator<String> comparator = Ordering.natural().reverse();
550       ImmutableSortedMap<String, Integer> map
551           = new ImmutableSortedMap.Builder<String, Integer>(comparator)
552               .put("one", 1)
553               .put("two", 2)
554               .put("three", 3)
555               .put("four", 4)
556               .put("five", 5)
557               .build();
558       assertMapEquals(map,
559           "two", 2, "three", 3, "one", 1, "four", 4, "five", 5);
560       assertSame(comparator, map.comparator());
561     }
562   }
563 
564   public void testNullGet() {
565     ImmutableSortedMap<String, Integer> map = ImmutableSortedMap.of("one", 1);
566     assertNull(map.get(null));
567   }
568 
569   private static <K, V> void assertMapEquals(Map<K, V> map,
570       Object... alternatingKeysAndValues) {
571     assertEquals(map.size(), alternatingKeysAndValues.length / 2);
572     int i = 0;
573     for (Entry<K, V> entry : map.entrySet()) {
574       assertEquals(alternatingKeysAndValues[i++], entry.getKey());
575       assertEquals(alternatingKeysAndValues[i++], entry.getValue());
576     }
577   }
578 
579   private static class IntHolder implements Serializable {
580     public int value;
581 
582     public IntHolder(int value) {
583       this.value = value;
584     }
585 
586     @Override public boolean equals(Object o) {
587       return (o instanceof IntHolder) && ((IntHolder) o).value == value;
588     }
589 
590     @Override public int hashCode() {
591       return value;
592     }
593 
594     private static final long serialVersionUID = 5;
595   }
596 
597   public void testMutableValues() {
598     IntHolder holderA = new IntHolder(1);
599     IntHolder holderB = new IntHolder(2);
600     Map<String, IntHolder> map
601         = ImmutableSortedMap.of("a", holderA, "b", holderB);
602     holderA.value = 3;
603     assertTrue(map.entrySet().contains(Maps.immutableEntry("a", new IntHolder(3))));
604     Map<String, Integer> intMap
605         = ImmutableSortedMap.of("a", 3, "b", 2);
606     assertEquals(intMap.hashCode(), map.entrySet().hashCode());
607     assertEquals(intMap.hashCode(), map.hashCode());
608   }
609 
610   @SuppressWarnings("unchecked") // varargs
611   public void testHeadMapInclusive() {
612     Map<String, Integer> map =
613         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).headMap("three", true);
614     assertThat(map.entrySet()).has().exactly(
615         Maps.immutableEntry("one", 1),
616         Maps.immutableEntry("three", 3)).inOrder();
617   }
618 
619   @SuppressWarnings("unchecked") // varargs
620   public void testHeadMapExclusive() {
621     Map<String, Integer> map =
622         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).headMap("three", false);
623     assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1)).inOrder();
624   }
625 
626   @SuppressWarnings("unchecked") // varargs
627   public void testTailMapInclusive() {
628     Map<String, Integer> map =
629         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).tailMap("three", true);
630     assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3),
631         Maps.immutableEntry("two", 2)).inOrder();
632   }
633 
634   @SuppressWarnings("unchecked") // varargs
635   public void testTailMapExclusive() {
636     Map<String, Integer> map =
637         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).tailMap("three", false);
638     assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("two", 2)).inOrder();
639   }
640 
641   @SuppressWarnings("unchecked") // varargs
642   public void testSubMapExclusiveExclusive() {
643     Map<String, Integer> map =
644         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", false, "two", false);
645     assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3)).inOrder();
646   }
647 
648   @SuppressWarnings("unchecked") // varargs
649   public void testSubMapInclusiveExclusive() {
650     Map<String, Integer> map =
651         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", true, "two", false);
652     assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1),
653         Maps.immutableEntry("three", 3)).inOrder();
654   }
655 
656   @SuppressWarnings("unchecked") // varargs
657   public void testSubMapExclusiveInclusive() {
658     Map<String, Integer> map =
659         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", false, "two", true);
660     assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3),
661         Maps.immutableEntry("two", 2)).inOrder();
662   }
663 
664   @SuppressWarnings("unchecked") // varargs
665   public void testSubMapInclusiveInclusive() {
666     Map<String, Integer> map =
667         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", true, "two", true);
668     assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1),
669         Maps.immutableEntry("three", 3), Maps.immutableEntry("two", 2)).inOrder();
670   }
671 
672   private static class SelfComparableExample implements Comparable<SelfComparableExample> {
673     @Override
674     public int compareTo(SelfComparableExample o) {
675       return 0;
676     }
677   }
678 
679   public void testBuilderGenerics_SelfComparable() {
680     ImmutableSortedMap.Builder<SelfComparableExample, Object> natural =
681         ImmutableSortedMap.naturalOrder();
682 
683     ImmutableSortedMap.Builder<SelfComparableExample, Object> reverse =
684         ImmutableSortedMap.reverseOrder();
685   }
686 
687   private static class SuperComparableExample extends SelfComparableExample {}
688 
689   public void testBuilderGenerics_SuperComparable() {
690     ImmutableSortedMap.Builder<SuperComparableExample, Object> natural =
691         ImmutableSortedMap.naturalOrder();
692 
693     ImmutableSortedMap.Builder<SuperComparableExample, Object> reverse =
694         ImmutableSortedMap.reverseOrder();
695   }
696 }
697